home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DJGPP / DJ111M3.ZIP / go32 / paging.c < prev    next >
C/C++ Source or Header  |  1994-02-09  |  36KB  |  1,262 lines

  1. /* This is file PAGING.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* Modified for DPMI Implement by H.Tsubakimoto */
  17. /* NUR paging algorithm by rcharif@math.utexas.edu */
  18. /* Merged DPMI with V1.09+ code C. Sandmann sandmann@clio.rice.edu */
  19.  
  20. #include <stdio.h>
  21. #include <dos.h>
  22. #include <fcntl.h>
  23. #include <io.h>
  24. #include <sys/stat.h>
  25. #include <bios.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28.  
  29. #include "gotypes.h"
  30. #include "paging.h"
  31. #include "graphics.h"
  32. #include "tss.h"
  33. #include "idt.h"
  34. #include "gdt.h"
  35. #include "valloc.h"
  36. #include "dalloc.h"
  37. #include "utils.h"
  38. #include "aout.h"
  39. #include "mono.h"
  40. #include "vcpi.h"
  41. #include "dpmi.h"
  42. #include "extdebug.h"
  43. #include "exphdlr.h"
  44. #include "stubinfo.h"
  45. #include "proginfo.h"
  46. #include "control.h"
  47.  
  48. #define VERBOSE 0
  49.  
  50. /* #define KEEP_ON_EXEC */
  51.  
  52. #define MAX_PAGING_NUM 2
  53.  
  54.  
  55. #define DOS_PAGE 256            /*  1MB / 4KB = 256 Pages  */
  56.  
  57.  
  58. extern char transfer_buffer[4096];
  59.  
  60. extern word32 ptr2linear(void far *ptr);
  61.  
  62. struct {
  63.   word16 limit;
  64.   word32 base;
  65. } gdt_phys, idt_phys;
  66.  
  67. CLIENT  client;         /*  VCPI Change Mode Structure  */
  68. word32  abs_client;     /*  _DS * 16L + &client         */
  69. far32   vcpi_entry;
  70. SYS_TBL int_descriptor;
  71. SYS_TBL gbl_descriptor;
  72.  
  73. extern word16 vcpi_installed;   /*  VCPI Installed Flag  */
  74. extern near protect_entry();
  75. word32 DPMI_STACK = 0x40000L; /* 256Kb Min */
  76. #define DPMIgetpage 0xffffL /* 64K instead of 4K for speed */
  77. DPMImemory DPMImem;         /* protected memory block */
  78. static word32 oldbase;     /* DPMI selector base for allocated memory */
  79. static word16 DPMIselect; /* selectors for application */
  80.                           /* DPMIselect + 0  : data selector */
  81.                           /* DPMIselect + 8  : code selector */
  82.                           /* DPMIselect + 16 : stack selector */ 
  83.                           /* DPMIselect + 24 : linear 1Mb range */ 
  84.  
  85. extern TSS *utils_tss;
  86. extern int debug_mode;
  87. extern word32 mem_avail;
  88. extern int self_contained;
  89. extern long header_offset;
  90.  
  91. word16 core_selector, arena_ds, arena_cs;
  92.  
  93. AREAS areas[MAX_AREA];
  94. #if VERBOSE
  95. static char *aname[MAX_AREA] = {
  96.         "text ",
  97.         "data ",
  98.         "bss  ",
  99.         "arena",
  100.         "stack",
  101.         "vga  ",
  102.         "syms ",
  103.         "syms2",
  104.         "emu"
  105. };
  106. #endif
  107. static char achar[MAX_AREA] = "tdbmsg?e";
  108.  
  109. word32 far *pd = 0;
  110. word8 pd_seg[1024];
  111. word32 far *vcpi_pt = 0;
  112. word8 paging_buffer[4096*MAX_PAGING_NUM];
  113.  
  114. word32 screen_primary, screen_secondary;
  115.  
  116. word32 ptr2linear(void far *ptr)
  117. {
  118.   return (word32)FP_SEG(ptr) * 16L + (word32)FP_OFF(ptr);
  119. }
  120.  
  121. static word32 far2pte(void far *ptr, word32 flags)
  122. {
  123.   return (vcpi_pt[(int)(((word32)ptr) >> 24)] & 0xfffff000L) | flags;
  124. }
  125.  
  126. static word32 pn2pte(unsigned pn, word32 flags)
  127. {
  128.   return (vcpi_pt[pn] & 0xfffff000L) | flags;
  129. }
  130.  
  131. static void setDPMISelectors(int firsttime)
  132. {
  133.   int selfail;
  134.  
  135.   selfail = 0;
  136.   if(!DPMIassignSelector(DPMIselect, 0xc0b3, DPMImem.address,
  137.       DPMImem.bytes - 1 ) ) selfail = 1; /* win 3.1 needs f, 3.0 b */
  138.  
  139.   if(firsttime){
  140.     if(!DPMIassignSelector(DPMIselect + 8, 0xc0bb, DPMImem.address, 
  141.         DPMImem.bytes - 1) ) selfail |= 2;
  142.     if(!DPMIassignSelector(DPMIselect + 16, 0xc0b7, DPMImem.address,
  143.         (areas[A_stack].first_addr - 1) ) ) selfail |= 4;
  144.   } else if(DPMImem.address != oldbase) {
  145.     if(!DPMISelectorBase(DPMIselect + 8, DPMImem.address) ) selfail |= 10;
  146.     if(!DPMISelectorBase(DPMIselect + 16, DPMImem.address) ) selfail |= 12;
  147.     if(using_external_debugger) {
  148.       DPMIrealMode();
  149.       clear_break_DPMI();       /* This clears the breakpoints */
  150.       set_break_DPMI();         /* This resets them with new base */
  151.       DPMIprotectedMode();
  152.     }
  153.   }
  154.   oldbase = DPMImem.address;
  155.  
  156. #if VERBOSE
  157.   if(selfail) {
  158.     /* For some reason stack #4 fails under OS2 but it still works; thus
  159.        the workaround is to ignore this section unless in verbose mode */
  160.     DPMIrealMode();
  161.     fprintf(stderr,"DPMI: AssignSelector %d failed!\n",selfail);
  162. /*    exit(3);  */
  163.     DPMIprotectedMode();  /* Only if exit commented */
  164.   }
  165. #endif
  166. }
  167.  
  168. void loadAout(const AREAS* areas)
  169. {
  170.   word32 count = areas->last_addr + 1 - areas->first_addr;
  171.  
  172.   if (count > 0) {
  173.     word32 loadAddr = areas->first_addr;
  174.     lseek(areas->fileno, areas->foffset, 0);
  175.     while (count > 0) {
  176.       word16 readBytes;
  177.       word16 bytes = (count > 4096) ? 4096 : (word16)count;
  178.       readBytes = read(areas->fileno, transfer_buffer, bytes);
  179.       if (readBytes < bytes) memset(transfer_buffer + readBytes, 0, bytes - readBytes);
  180.       memput(loadAddr, transfer_buffer, bytes);
  181.       loadAddr += bytes;
  182.       count -= bytes;
  183.     }
  184.   }
  185. }
  186.  
  187. void clearDPMIstate(void)
  188. {
  189.   DPMIfree(&DPMImem);  /* QDPMI bug fix - child processes don't free memory */
  190. }
  191.  
  192. static void saveDPMIstate(void)
  193. {
  194.   int a;
  195.   word32 firsta, lengtha;
  196.   word16 bytes;
  197.   unsigned block;
  198.  
  199.   block = 0;
  200.   for (a=0; a<MAX_AREA; a++) {
  201.     firsta = areas[a].first_addr;
  202.     if ( a == A_stack ) firsta = a_tss.tss_esp & 0xfffff000L;
  203.     lengtha = areas[a].last_addr - firsta + 1;
  204.     while (lengtha > 0) {
  205.       bytes = (lengtha > 4096) ? 4096 : (word16)lengtha;
  206.       Pmemget(DPMIselect, firsta, paging_buffer, bytes);
  207.       dwrite(paging_buffer, block++);
  208.       firsta += bytes;
  209.       lengtha -= bytes;
  210.     }
  211.   }
  212.   DPMIprotectedMode();
  213.   DPMIfree(&DPMImem);
  214.   restoreDPMIvector();
  215.   DPMIrealMode();
  216. }
  217.  
  218. static void restoreDPMIstate(void)
  219. {
  220.   int a;
  221.   word32 firsta, lengtha;
  222.   word16 bytes;
  223.   unsigned block;
  224.  
  225.   DPMIprotectedMode();
  226.   setDPMIvector();
  227.   lengtha = (areas[A_arena].last_addr + 1 + DPMIgetpage) & ~DPMIgetpage;
  228.   if (! DPMIalloc(&DPMImem, lengtha)) {
  229.     DPMIrealMode();
  230.     fprintf(stderr,"\nDPMI: Not enough memory (0x%08lx bytes).\n", lengtha);
  231.     exit(3);
  232.   }
  233.   setDPMISelectors(0);
  234.   DPMIrealMode();
  235.   firsta = areas[A_arena].last_addr + 1;
  236.   if(lengtha > firsta)
  237.     Pmemset(DPMIselect, firsta, 0, lengtha - firsta );
  238.  
  239.   block = 0;
  240.   for (a=0; a<MAX_AREA; a++) {
  241.     firsta = areas[a].first_addr;
  242.     if ( a == A_stack ) firsta = a_tss.tss_esp & 0xfffff000L;
  243.     lengtha = areas[a].last_addr - firsta + 1;
  244.     while (lengtha > 0) {
  245.       bytes = (lengtha > 4096) ? 4096 : (word16)lengtha;
  246.       dread(paging_buffer, block++);
  247.       Pmemput(DPMIselect, firsta, paging_buffer, bytes);
  248.       firsta += bytes;
  249.       lengtha -= bytes;
  250.     }
  251.   }
  252. }
  253.  
  254. int changeBreak(word32 breakPoint)
  255. {
  256.   word32 oldbytes, newbytes;
  257.  
  258.   newbytes = (breakPoint + DPMIgetpage) & ~DPMIgetpage; /* 64K for performance */
  259.   oldbytes = DPMImem.bytes;
  260.   if (newbytes < areas[A_arena].first_addr) newbytes=areas[A_arena].first_addr;
  261. #if VERBOSE
  262.   fprintf(stderr,"changeBreak: old=0x%08lx  break=0x%08lx  new=0x%08lx\n",
  263.     oldbytes, breakPoint, newbytes);
  264. #endif
  265.   if (DPMImem.bytes != newbytes) {
  266.     DPMIprotectedMode();
  267.     if (! DPMIrealloc(&DPMImem, newbytes)) {
  268.       DPMIrealMode();
  269.       fprintf(stderr,"\nDPMI: Not enough memory (0x%08lx bytes).\n", newbytes);
  270.       return 0;
  271.     }
  272.     setDPMISelectors(0);
  273.     DPMIrealMode();
  274.   }
  275.   if(newbytes > oldbytes) 
  276.     Pmemset(DPMIselect, oldbytes, 0, newbytes - oldbytes );
  277.   return 1;
  278. }
  279.  
  280. /*  VCPI Get Interface  */
  281. void    link_vcpi(word32 far *dir, word32 far *table)
  282. {
  283.  
  284.   vcpi_entry.selector = g_vcpicode * 8;
  285.   vcpi_entry.offset32 = get_interface(table,&gdt[g_vcpicode]);
  286.   client.page_table   = far2pte(dir, 0); /* (word32)dir>>12; */
  287.   client.gdt_address  = ptr2linear(&gdt_phys);
  288.   client.idt_address  = ptr2linear(&idt_phys);
  289.   client.ldt_selector = 0;
  290.   client.tss_selector = g_ctss * 8;
  291.   client.entry_eip    = (word16)protect_entry;
  292.   client.entry_cs     = g_rcode * 8;
  293.  
  294.   abs_client = ptr2linear(&client);
  295. }
  296.  
  297. void handle_screen_swap(word32 far *pt)
  298. {
  299.   struct REGPACK r;
  300.   int have_mono=0;
  301.   int have_color=0;
  302.   int have_graphics=0;
  303.   int save, new;
  304.  
  305.   r.r_ax = 0x1200;
  306.   r.r_bx = 0xff10;
  307.   r.r_cx = 0xffff;
  308.   intr(0x10, &r);
  309.   if (r.r_cx == 0xffff)
  310.     pokeb(0x40, 0x84, 24); /* the only size for CGA/MDA */
  311.  
  312.   if (!vcpi_installed || (pt[0xb8] & (PT_U|PT_W)) == (PT_W|PT_U))
  313.   {
  314.     save = peekb(screen_seg, 0);
  315.     pokeb(screen_seg, 0, ~save);
  316.     new = peekb(screen_seg, 0);
  317.     pokeb(screen_seg, 0, save);
  318.     if (new == ~save)
  319.       have_color = 1;
  320.   }
  321.  
  322.   if (!vcpi_installed || (pt[0xb0] & (PT_U|PT_W)) == (PT_W|PT_U))
  323.   {
  324.     save = peekb(0xb000, 0);
  325.     pokeb(0xb000, 0, ~save);
  326.     new = peekb(0xb000, 0);
  327.     pokeb(0xb000, 0, save);
  328.     if (new == ~save)
  329.       have_mono = 1;
  330.   }
  331.  
  332.   r.r_ax = 0x0f00;
  333.   intr(0x10, &r);
  334.   if ((r.r_ax & 0xff) > 0x07)
  335.     have_graphics = 1;
  336.  
  337.   if (have_graphics && have_mono)
  338.     have_color = 1;
  339.   else if (have_graphics && have_color)
  340.     have_mono = 1;
  341.  
  342.   screen_primary = 0xe00b8000L;
  343.   screen_secondary = 0xe00b0000L;
  344.  
  345.   if (have_color && !have_mono)
  346.   {
  347.     screen_secondary = 0xe00b8000L;
  348.     return;
  349.   }
  350.   if (have_mono & !have_color)
  351.   {
  352.     screen_primary = 0xe00b0000L;
  353.     return;
  354.   }
  355.  
  356.   if ((biosequip() & 0x0030) == 0x0030) /* mono mode, swap! */
  357.   {
  358.     screen_primary = 0xe00b0000L;
  359.     screen_secondary = 0xe00b8000L;
  360.     return;
  361.   }
  362. }
  363.  
  364. void paging_set_file(char *fname)
  365. {
  366.   word32 newbytes;
  367.   word32 far *pt;
  368.   FILEHDR filehdr;
  369.   AOUTHDR aouthdr;
  370.   SCNHDR scnhdr[3];
  371.   GNU_AOUT gnu_aout;
  372.   unsigned short *exe_hdr;
  373.   int i;
  374.   int aout_f;
  375.  
  376.   aout_f = open(fname, O_RDONLY|O_BINARY);
  377.   if (aout_f < 0)
  378.   {
  379.     fprintf(stderr, "Can't open file <%s>\n", fname);
  380.     exit(1);
  381.   }
  382.   
  383.   areas[A_text].fileno = aout_f;
  384.   areas[A_data].fileno = aout_f;
  385.   for (i=A_bss; i<A_max; i++)
  386.     areas[i].fileno = 0;
  387.  
  388.   if (topline_info)
  389.     for (i=0; fname[i]; i++)
  390.       poke(screen_seg, i*2+10, fname[i] | 0x0700);
  391.  
  392.   lseek(aout_f, header_offset, 0);
  393.   read(aout_f, &filehdr, sizeof(filehdr));
  394.  
  395.   if (filehdr.f_magic == 0x5a4d) /* .EXE */
  396.   {
  397.     exe_hdr = (unsigned short *)&filehdr;
  398.     header_offset += (long)exe_hdr[2]*512L;
  399.     if (exe_hdr[1])
  400.       header_offset += (long)exe_hdr[1] - 512L;
  401.     lseek(aout_f, header_offset, 0);
  402.     read(aout_f, &filehdr, sizeof(filehdr));
  403.   }
  404.  
  405.   if (filehdr.f_magic != 0x14c)
  406.   {
  407.     lseek(aout_f, header_offset, 0);
  408.     read(aout_f, &gnu_aout, sizeof(gnu_aout));
  409.     a_tss.tss_eip = gnu_aout.entry;
  410.     aouthdr.tsize = gnu_aout.tsize;
  411.     aouthdr.dsize = gnu_aout.dsize;
  412.     aouthdr.bsize = gnu_aout.bsize;
  413.   }
  414.   else
  415.   {
  416.     if (filehdr.f_opthdr)
  417.     {
  418.       read(aout_f, &aouthdr, sizeof(aouthdr));
  419.       a_tss.tss_eip = aouthdr.entry;
  420.     }
  421.     else
  422.       a_tss.tss_eip = 0;
  423.     read(aout_f, scnhdr, sizeof(scnhdr));
  424.     if (! filehdr.f_opthdr)
  425.     {
  426.       aouthdr.tsize = scnhdr[0].s_size;
  427.       aouthdr.dsize = scnhdr[1].s_size;
  428.       aouthdr.bsize = scnhdr[2].s_size;
  429.     }
  430.   }
  431.   arena_cs =
  432.   a_tss.tss_cs = g_acode*8;
  433.   arena_ds =
  434.   a_tss.tss_ds =
  435.   a_tss.tss_es =
  436.   a_tss.tss_fs =
  437.   a_tss.tss_ss = g_adata*8;
  438.   a_tss.tss_esp = 0x7ffffffcL;
  439.  
  440.   if (filehdr.f_magic == 0x14c && filehdr.f_opthdr)
  441.   {
  442.     areas[A_text].first_addr = aouthdr.text_start + ARENA;
  443.     areas[A_text].foffset = scnhdr[0].s_scnptr + header_offset;
  444.     areas[A_text].last_addr = areas[A_text].first_addr + aouthdr.tsize - 1;
  445.   }
  446.   else if (filehdr.f_magic == 0x14c && debug_mode)
  447.   {
  448.     areas[A_text].first_addr = scnhdr[0].s_vaddr + ARENA;
  449.     areas[A_text].foffset = scnhdr[0].s_scnptr + header_offset;
  450.     areas[A_text].last_addr = areas[A_text].first_addr + scnhdr[0].s_size - 1;
  451.   }
  452.   else if (filehdr.f_magic == 0x10b)
  453.   {
  454.     areas[A_text].first_addr = ARENA;
  455.     if (a_tss.tss_eip >= 0x1000)        /* leave space for null reference */
  456.       areas[A_text].first_addr += 0x1000;    /* to cause seg fault */
  457.     areas[A_text].foffset = header_offset;
  458.     areas[A_text].last_addr = areas[A_text].first_addr + aouthdr.tsize + 0x20 - 1;
  459.   }
  460.   else if (debug_mode && filehdr.f_magic == 0x107)
  461.   {
  462.     struct stat sbuf;
  463.     fstat(aout_f, &sbuf);
  464.     areas[A_text].first_addr = ARENA;
  465.     areas[A_text].foffset = 0x20 + header_offset;
  466.     areas[A_text].last_addr = sbuf.st_size + ARENA - 0x20;
  467.   }
  468.   else if (debug_mode)
  469.   {
  470.     struct stat sbuf;
  471.     fstat(aout_f, &sbuf);
  472.     areas[A_text].first_addr = ARENA;
  473.     areas[A_text].foffset = header_offset;
  474.     areas[A_text].last_addr = sbuf.st_size + ARENA;
  475.   }
  476.   else
  477.   {
  478.     fprintf(stderr, "Unknown file type 0x%x (0%o)\n", filehdr.f_magic, filehdr.f_magic);
  479.     exit(-1);
  480.   }
  481.   if (debug_mode)
  482.     fprintf(stderr, "%ld+", aouthdr.tsize);
  483.  
  484.   if (filehdr.f_magic == 0x14c)
  485.   {
  486.     areas[A_data].first_addr = aouthdr.data_start + ARENA;
  487.     areas[A_data].foffset = scnhdr[1].s_scnptr + header_offset;
  488.   }
  489.   else
  490.   {
  491.     areas[A_data].first_addr = (areas[A_text].last_addr+0x3fffffL)&~0x3fffffL;
  492.     areas[A_data].foffset = ((aouthdr.tsize + 0x20 + 0xfffL) & ~0xfffL) + header_offset;
  493.   }
  494.   areas[A_data].last_addr = areas[A_data].first_addr + aouthdr.dsize - 1;
  495.   if (debug_mode)
  496.     fprintf(stderr, "%ld+", aouthdr.dsize);
  497.  
  498.   areas[A_bss].first_addr = areas[A_data].last_addr + 1;
  499.   areas[A_bss].foffset = -1;
  500.   areas[A_bss].last_addr = areas[A_bss].first_addr + aouthdr.bsize - 1;
  501.   if (debug_mode)
  502.     fprintf(stderr, "%ld = %ld\n", aouthdr.bsize,
  503.       aouthdr.tsize+aouthdr.dsize+aouthdr.bsize);
  504.  
  505.   areas[A_arena].first_addr = (areas[A_bss].last_addr + 1 + 7) & ~7L;
  506.   areas[A_arena].last_addr = areas[A_arena].first_addr - 1;
  507.   areas[A_arena].foffset = -1;
  508.  
  509.   if(!use_DPMI)
  510.   {
  511.     areas[A_stack].first_addr = 0x50000000L;
  512.     areas[A_stack].last_addr = 0x8fffffffL;
  513.     areas[A_stack].foffset = -1;
  514.   
  515.     areas[A_vga].first_addr = 0xe0000000L;
  516.     areas[A_vga].last_addr = 0xe03fffffL;
  517.     areas[A_vga].foffset = -1;
  518.   
  519.     areas[A_syms].first_addr = 0xa0000000L;
  520.     areas[A_syms].last_addr = 0xafffffffL;
  521.     areas[A_syms].foffset = -1;
  522.   
  523.     pd = (word32 far *)((long)valloc(VA_640) << 24);
  524.     vcpi_pt = pt = (word32 far *)((long)valloc(VA_640) << 24);
  525.     for (i=0; i<1024; i++)
  526.     {
  527.       pd[i] = 0;
  528.       pd_seg[i] = 0;
  529.     }
  530.   
  531.     if (vcpi_installed)
  532.     {
  533.       link_vcpi(pd,pt);           /*  Get VCPI Page Table  */
  534.       for ( i=0; i<1024; i++)
  535.         if (pt[i] & PT_P)
  536.           pt[i] |= PT_I;
  537.     }
  538.     else
  539.     {
  540.       for (i=0; i < DOS_PAGE; i++)
  541.         pt[i] = ((unsigned long)i<<12) | PT_P | PT_W | PT_I;
  542.       for (; i<1024; i++)
  543.         pt[i] = 0;
  544.     }
  545.  
  546.     pd[0] = 
  547.       pd[0x3c0] = far2pte(pt, PT_P | PT_W | PT_I);  /* map 1:1 1st Mb */
  548.     pd_seg[0] = 
  549.       pd_seg[0x3c0] = (word32)pt >> 24;
  550.   
  551.     gdt_phys.limit = gdt[g_gdt].lim0;
  552.     gdt_phys.base = ptr2linear(&gdt);
  553.     idt_phys.limit = gdt[g_idt].lim0;
  554.     idt_phys.base = ptr2linear(&idt);
  555.   
  556.     handle_screen_swap(pt);
  557.     a_tss.tss_ebx = screen_primary;
  558.     a_tss.tss_ebp = screen_secondary;
  559.     prog_info.linear_address_of_primary_screen = screen_primary;
  560.     prog_info.linear_address_of_secondary_screen = screen_secondary;
  561.   
  562. /* CB changes: two page tables + stuff for graphics page fault handler */
  563. /* to move around page tables in the page directory */
  564. /* OLD:
  565.  * graphics_pt = (word32 far *)((long)valloc(VA_640) << 24);
  566.  * graphics_pt_lin = ptr2linear(graphics_pt);
  567.  * for (i=0; i<1024; i++)
  568.  *   graphics_pt[i] = 0x000a0000L | ((i * 4096L) & 0xffffL) | PT_W | PT_U;
  569.  * pd[0x380] = far2pte(graphics_pt, PT_P | PT_W | PT_U);
  570.  * pd_seg[0x380] = (word32)graphics_pt >> 24;
  571.  */
  572.   graphics_pd       = &pd[0x380];
  573.   graphics_pd_seg     = &pd_seg[0x380];
  574.   graphics_pd_lin     = ptr2linear(graphics_pd);
  575.   graphics_pd_seg_lin = ptr2linear(graphics_pd_seg);
  576.   graphics_pt1              = (word32 far *)((long)valloc(VA_640) << 24);
  577.   graphics_pt2              = (word32 far *)((long)valloc(VA_640) << 24);
  578.   graphics_pt1_lin    = ptr2linear(graphics_pt1);
  579.   graphics_pt2_lin    = ptr2linear(graphics_pt2);
  580.   graphics_pt1_loc    = 0;                            /* first RW page */
  581.   graphics_pt2_loc    = (0x03000000L / 4096L / 1024L);  /* first page of the 16 MB write only area */
  582.   graphics_pd[(word16)graphics_pt1_loc] = far2pte(graphics_pt1,(PT_P | PT_W | PT_U));
  583.   graphics_pd[(word16)graphics_pt2_loc] = far2pte(graphics_pt2,(PT_P | PT_W | PT_U));
  584.   graphics_pd_seg[(word16)graphics_pt1_loc] = (word32)graphics_pt1 >> 24;
  585.   graphics_pd_seg[(word16)graphics_pt2_loc] = (word32)graphics_pt2 >> 24;
  586.   for(i = 0; i < 1024; i++) {
  587.     graphics_pt1[i] = 0L;
  588.     graphics_pt2[i] = 0L;
  589.   }
  590. /* end CB changes */
  591.   
  592.     c_tss.tss_cr3 = 
  593.     a_tss.tss_cr3 = 
  594.     o_tss.tss_cr3 = 
  595.     i_tss.tss_cr3 = 
  596.     p_tss.tss_cr3 = 
  597.     f_tss.tss_cr3 = 
  598.     r_tss.tss_cr3 = 
  599.     v74_tss.tss_cr3 = 
  600.     v78_tss.tss_cr3 = 
  601.     v79_tss.tss_cr3 = far2pte(pd, 0);
  602.   
  603.     a_tss.tss_esi = far2pte(pd,0) >> 12; /* PID */
  604.     prog_info.pid = far2pte(pd,0) >> 12;
  605.   
  606.   }
  607.   else   /* use_DPMI */
  608.   {
  609.   
  610.     if (areas[A_bss].last_addr < 0x11000L)
  611.      areas[A_bss].last_addr = 0x11000L;
  612.     handle_screen_swap(NULL);
  613.     a_tss.tss_ebx = screen_primary;
  614.     a_tss.tss_ebp = screen_secondary;
  615.     prog_info.linear_address_of_primary_screen = screen_primary;
  616.     prog_info.linear_address_of_secondary_screen = screen_secondary;
  617.     a_tss.tss_esi = FP_SEG(paging_buffer);
  618.     prog_info.pid = FP_SEG(paging_buffer);
  619. #if VERBOSE
  620.     fprintf(stderr,"%ld+%ld+%ld = %ld\n", aouthdr.tsize, aouthdr.dsize, aouthdr.bsize,
  621.       aouthdr.tsize+aouthdr.dsize+aouthdr.bsize);
  622. #endif
  623.   
  624.     /* In certain instances, there is a large gap between text and data.  If it
  625.        is larger than the stack size, lets take advantage of it. */
  626.   
  627.     if (areas[A_data].first_addr - areas[A_text].last_addr <= DPMI_STACK)
  628.     {  /* No room, put stack between bss and arena */
  629.       areas[A_stack].first_addr = (areas[A_bss].last_addr + 1 + 0xfff) & ~0xfff;
  630.       if (areas[A_stack].first_addr < 0x11000L) 
  631.         areas[A_stack].first_addr = 0x11000L; /* Some bizzare windows bug */
  632.       areas[A_stack].last_addr = areas[A_stack].first_addr + DPMI_STACK - 1;
  633.       areas[A_arena].first_addr = areas[A_stack].last_addr + 1;
  634.       areas[A_arena].last_addr = areas[A_stack].last_addr;
  635.   } else {  /* Put stack in gap */
  636.       areas[A_stack].last_addr = areas[A_data].first_addr - 1;
  637. /*    areas[A_stack].first_addr = areas[A_stack].last_addr - DPMI_STACK + 1; */
  638.       areas[A_stack].first_addr = (areas[A_text].last_addr + 1 + 0xfff) & ~0xfff;
  639.       if (areas[A_stack].first_addr < 0x11000L) 
  640.         areas[A_stack].first_addr = 0x11000L; /* Some bizzare windows bug */
  641.     }
  642.     areas[A_vga].first_addr =
  643.      areas[A_syms].first_addr =
  644.      areas[A_syms2].first_addr = 1; /* Not used */
  645.     areas[A_vga].last_addr =
  646.      areas[A_syms].last_addr =
  647.      areas[A_syms2].last_addr = 0;   /* len zero */
  648.   
  649.     /* Here and in changeBreak we use 64K breaks to minimize calls to DPMI */
  650.     newbytes = (areas[A_arena].last_addr + 1 + DPMIgetpage) & ~DPMIgetpage;
  651.     DPMIprotectedMode();
  652.     if (! DPMIalloc(&DPMImem, newbytes))
  653.     {
  654.       DPMIrealMode();
  655.       fprintf(stderr,"DPMI: Not enough memory (0x%08lx bytes).\n", newbytes);
  656.       exit(1);
  657.     }
  658.     DPMIselect = DPMIselector(4);
  659.     if (DPMIselect == 0)
  660.     {
  661.       DPMIrealMode();
  662.       fprintf(stderr,"DPMI: Not enough selectors.\n");
  663.       exit(1);
  664.     }
  665.     setDPMISelectors(1);
  666.     DPMIassignSelector(DPMIselect+24, 0xc0b3, 0L, 0xfffffL);
  667.     DPMIrealMode();
  668.  
  669.     core_selector =  
  670.     a_tss.tss_gs =
  671.     prog_info.selector_for_linear_memory = (word16)(DPMIselect+24);
  672.   
  673.     a_tss.tss_eax = (word32)(DPMIselect + 24) << 16;  /* Hi word for "core" selector */
  674.     arena_ds = a_tss.tss_ds = a_tss.tss_es = a_tss.tss_fs = DPMIselect;
  675.     arena_cs = a_tss.tss_cs = DPMIselect + 8;
  676.     a_tss.tss_ss = DPMIselect + 16;
  677.     a_tss.tss_esp = areas[A_stack].last_addr + 1;
  678.     a_tss.tss_eflags = 0x0202;
  679.  
  680.     r_tss.tss_es = r_tss.tss_fs = DPMIselect;
  681.     r_tss.tss_cs = DPMIselect + 8;
  682.   
  683.     loadAout(&areas[A_text]);
  684.     loadAout(&areas[A_data]);
  685.     Pmemset(DPMIselect, areas[A_bss].first_addr, 0, areas[A_bss].last_addr + 1 - areas[A_bss].first_addr);
  686.     Pmemset(DPMIselect, areas[A_arena].first_addr, 0, newbytes - areas[A_arena].first_addr);
  687.   
  688.     close(aout_f);
  689.   } /* end else use_DPMI */
  690.  
  691. #if VERBOSE
  692.     for (i=0; i<5; i++)
  693.       fprintf(stderr,"%d %-10s %08lx-%08lx (offset 0x%08lx)\n", i, aname[i], areas[i].first_addr, areas[i].last_addr, areas[i].foffset);
  694. #endif
  695. }
  696.  
  697. static update_status(int c, int col)
  698. {
  699.   int r;
  700.   r = peek(screen_seg, 2*79);
  701.   poke(screen_seg, 2*col, c);
  702.   return r;
  703. }
  704.  
  705. static int cant_ask_for(int32 amount)
  706. {
  707.   static word32 reserved = 0;
  708.   static word32 used_at_first = 0;
  709.   word32 max;
  710.   
  711.   if (use_DPMI)
  712.     return 0;
  713.   if (used_at_first == 0)
  714.     used_at_first = (valloc_used() - dalloc_used()) * 4096L + 8192L /* stack */;
  715.   max = valloc_max_size()*4092L - used_at_first;    /* 4096 - PTE */
  716.  
  717.   if (reserved + amount >= max)
  718.     max += dalloc_max_size() * 4092L;
  719.  
  720.   if (reserved + amount < max)
  721.   {
  722.     reserved += amount;
  723.     return 0;
  724.   }
  725.   return 1;
  726. }
  727.  
  728. word32 paging_brk(word32 b)
  729. {
  730.   word32 r;
  731.  
  732.   r = (areas[A_arena].last_addr - ARENA + 1 + 7) & ~7;  /* Even value */
  733.   if (use_DPMI)
  734.     if (! changeBreak(b)) return -1L;
  735.   if (cant_ask_for(b-r))
  736.     return -1L;
  737.   areas[A_arena].last_addr = b + ARENA - 1;
  738.   return r;
  739. }
  740.  
  741. word32 paging_sbrk(int32 b)
  742. {
  743.   word32 r;
  744.  
  745.   r = (areas[A_arena].last_addr - ARENA + 1 + 7) & ~7;  /* Even value */
  746.   if (use_DPMI)
  747.     if (! changeBreak(r + b)) return -1L;
  748.   if (cant_ask_for(b))
  749.     return -1L;
  750.   areas[A_arena].last_addr = r + b + ARENA - 1;
  751.   return r;
  752. }
  753.  
  754. int page_is_valid(word32 vaddr)
  755. {
  756.   int a;
  757.   for (a=0; a<MAX_AREA; a++)
  758.     if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
  759.       return 1;
  760.   if ( use_DPMI )
  761.     return 0;
  762.   if (vaddr >= 0xf0000000L)
  763.     return 1;
  764.   return 0;
  765. }
  766.  
  767. int page_in(void)
  768. {
  769.   int old_status;
  770.   TSS *old_util_tss;
  771.   word32 far *pt;
  772.   word32 vaddr, cnt32;
  773.   word32 eaddr, vtran, vcnt, zaddr;
  774.   int pdi, pti, pn, a, count;
  775.   unsigned dblock;
  776.  
  777.   if (use_DPMI)
  778.     return 1;
  779.  
  780. #if 0
  781.   unsigned char buf[100];
  782.   sprintf(buf, "0x%08lx", a_tss.tss_cr2 - ARENA);
  783.   for (a=0; buf[a]; a++)
  784.     poke(screen_seg, 80+a*2, 0x0600 | buf[a]);
  785. #endif
  786.  
  787.   old_util_tss = utils_tss;
  788.   utils_tss = &f_tss;
  789.   vaddr = tss_ptr->tss_cr2;
  790.  
  791.   for (a=0; a<MAX_AREA; a++)
  792.     if ((vaddr <= areas[a].last_addr) && (vaddr >= areas[a].first_addr))
  793.       goto got_area;
  794.  
  795.   if (vaddr >= 0xf0000000L)
  796.   {
  797.     pdi = (word16)(vaddr >> 22) & 0x3ff;
  798.     if (!(pd[pdi] & PT_P))      /* put in a mapped page table */
  799.     {
  800.       pn = valloc(VA_640);
  801.       pt = (word32 far *)((word32)pn << 24);
  802.       if (pd[pdi] & PT_S)
  803.       {
  804.         dread(paging_buffer, (word16)(pd[pdi]>>12));
  805.         movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
  806.         dfree((word16)(pd[pdi]>>12));
  807.         pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
  808.         pd_seg[pdi] = pn;
  809.       }
  810.       else
  811.       {
  812.         pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
  813.         pd_seg[pdi] = pn;
  814.         vaddr &= 0x0fc00000L;
  815.         for (pti = 0; pti < 1024; pti++)
  816.           pt[pti] = PT_P | PT_W | PT_I | vaddr | (((word32)pti)<<12);
  817.       }
  818.       return 0;
  819.     }
  820.     pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
  821.     vaddr &= 0x0ffff000L;
  822.     pti = (word16)(vaddr>>12) & 0x3ff;
  823.     pt[pti] = vaddr | PT_P | PT_W | PT_I;
  824.     return 0;
  825.   }
  826.  
  827.   segfault(tss_ptr->tss_cr2);
  828.   return 1;
  829.  
  830. got_area:
  831.   vaddr &= 0xFFFFF000L;  /* points to beginning of page */
  832. #if 0 /* handled in protected mode for speed */
  833.   if (a == A_vga)
  834.     return graphics_fault(vaddr, graphics_pt);
  835. #endif
  836.  
  837. #if VERBOSE
  838.     printf("area(%d) - ", a);
  839. #endif
  840.  
  841.   if ((a == A_bss) & (vaddr < areas[a].first_addr)) /* bss, but data too */
  842.   {
  843. #if VERBOSE
  844.       printf("split page (data/bss) detected - ");
  845. #endif
  846.     a = A_data; /* set to page in data */
  847.   }
  848.  
  849.   if (topline_info)
  850.     old_status = update_status(achar[a] | 0x0a00, 78);
  851. #if VERBOSE
  852.   printf("Paging in %s block for vaddr %#010lx -", aname[a], tss_ptr->tss_cr2-ARENA);
  853. #endif
  854.   pdi = (word16)(vaddr >> 22) & 0x3ff;
  855.   if (!(pd[pdi] & PT_P))        /* put in an empty page table if required */
  856.   {
  857.     pn = valloc(VA_640);
  858.     pt = (word32 far *)((word32)pn << 24);
  859.     if (pd[pdi] & PT_I)
  860.     {
  861.       dread(paging_buffer, (word16)(pd[pdi]>>12));
  862.       movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
  863.       dfree((word16)(pd[pdi] >> 12));
  864.       pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
  865.       pd_seg[pdi] = pn;
  866.     }
  867.     else
  868.     {
  869.       pd[pdi] = pn2pte(pn, PT_P | PT_W | PT_I | PT_S);
  870.       pd_seg[pdi] = pn;
  871.       for (pti=0; pti<1024; pti++)
  872.         pt[pti] = PT_W | PT_S;
  873.     }
  874.   }
  875.   else
  876.     pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
  877.   pti = (word16)(vaddr >> 12) & 0x3ff;
  878.   if (pt[pti] & PT_P)
  879.   {
  880.     utils_tss = old_util_tss;
  881.     if (topline_info)
  882.       update_status(old_status, 78);
  883.     return 0;
  884.   }
  885.   count = MAX_PAGING_NUM;
  886.   if (count > mem_avail/4)
  887.     count = 1;
  888.   if (pti + count > 1024)
  889.     count = 1024 - pti;
  890.   if (vaddr + count*4096L > areas[a].last_addr+4096L)
  891.     count = (word16)((areas[a].last_addr - vaddr + 4095) / 4096);
  892.   if (count < 1)
  893.     count = 1;
  894.   zaddr = eaddr = -1;
  895.   vtran = vaddr;
  896.   vcnt = 0;
  897.   for (; count; count--, pti++, vaddr+=4096)
  898.   {
  899.     if (pt[pti] & PT_P)
  900.       break;
  901.     if (eaddr != -1 && (pt[pti] & PT_I) != 0) 
  902.       break;  /* EastWind 1993 */
  903.     dblock = (word16)(pt[pti] >> 12);
  904.     pn = valloc(VA_1M);
  905.     pt[pti] &= 0xfffL & ~(word32)(PT_A | PT_D);
  906.     pt[pti] |= ((word32)pn << 12) | PT_P;
  907.  
  908.     if (pt[pti] & PT_I)
  909.     {
  910. #if VERBOSE
  911.       printf(" swap");
  912. #endif
  913.       dread(paging_buffer, dblock);
  914.       dfree(dblock);
  915.       memput(vaddr, paging_buffer, 4096);
  916.       pt[pti] &= ~(word32)(PT_A | PT_D);  /* clean dirty an accessed bits (set by memput) */
  917.     }
  918.     else
  919.     {
  920.       pt[pti] &= ~(word32)(PT_C);
  921.       if (areas[a].foffset != -1)
  922.       {
  923. #if VERBOSE
  924.         if (a == A_emu)
  925.           printf(" emu");
  926.         else
  927.           printf(" exec");
  928. #endif
  929.         if (eaddr == -1)
  930.         {
  931.           eaddr = areas[a].foffset + (vaddr - areas[a].first_addr);
  932.           vtran = vaddr;
  933.         }
  934.         cnt32 = areas[a].last_addr - vaddr + 1;
  935.         if (cnt32 > 4096)
  936.           cnt32 = 4096;
  937.         else
  938.           zaddr = vaddr;
  939.         vcnt += cnt32;
  940.       }
  941.       else
  942.       {
  943.         zero32(vaddr);
  944. #if VERBOSE
  945.         printf(" zero");
  946. #endif
  947.       }
  948.       pt[pti] |= PT_I;
  949.     }
  950. /*  if (paged_out_something) */
  951.       break;
  952.   }
  953.   if (eaddr != -1)
  954.   {
  955.     int cur_f, rsize, vc;
  956.     cur_f = areas[a].fileno;
  957.     lseek(cur_f, eaddr, 0);
  958.     rsize = read(cur_f, paging_buffer, (word16)vcnt);
  959.     if (rsize < vcnt)
  960.       memset(paging_buffer+rsize, 0, (word16)(vcnt-rsize));
  961.     if (zaddr != -1)
  962.       zero32(zaddr);
  963.     memput(vtran, paging_buffer, vcnt);
  964.     vc = (word16)(vcnt / 4096); /* don't reset BSS parts */
  965.     while (vc)
  966.     {
  967.       pdi = (word16)(vtran >> 22);
  968.       pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
  969.       pti = (word16)(vtran >> 12) & 0x3ff;
  970.       pt[pti] &= ~(word32)(PT_A | PT_D);  /* clean dirty an accessed bits (set by memput) */
  971.       vc--;
  972.       vtran += 4096;
  973.     }
  974.   }
  975. #if VERBOSE
  976.   printf("\n");
  977. #endif
  978.   utils_tss = old_util_tss;
  979.   if (topline_info)
  980.     update_status(old_status, 78);
  981.   return 0;
  982. }
  983.  
  984. static fInPageOutEverything = 0;
  985. static last_po_pdi = 0;
  986. static last_po_pti = 0;
  987. static last_pti = 0;
  988.  
  989. unsigned page_out(int where) /* return >= 0 page which is paged out, 0xffff if not */
  990. {
  991.   int start_pdi, start_pti, pti;
  992.   word32 far *pt, v, rv;
  993.   unsigned dblock;
  994.   int old_status;
  995.   if (topline_info)
  996.   {
  997.     old_status = update_status('>' | 0x0a00, 79);
  998.   }
  999.   start_pdi = last_po_pdi;
  1000.   start_pti = last_po_pti;
  1001.   if (where == VA_640)
  1002.   {
  1003.     for (pti = last_pti+1; pti != last_pti; pti = (pti+1)%1024)
  1004.       if ((pd[pti] & (PT_P | PT_S)) == (PT_P | PT_S))
  1005.       {
  1006.         dblock = dalloc();
  1007.         movedata(pd_seg[pti]<<8, 0, _DS, FP_OFF(paging_buffer), 4096);
  1008.         dwrite(paging_buffer, dblock);
  1009. #if VERBOSE
  1010.         printf ("out_640 %d\n", pti);
  1011. #endif
  1012.         pd[pti] &= 0xfff & ~(word32)(PT_P); /* no longer present */
  1013.         pd[pti] |= (long)dblock << 12;
  1014.         if (topline_info)
  1015.           update_status(old_status, 79);
  1016.         last_pti = pti;
  1017.         return pd_seg[pti];
  1018.       }
  1019.     return -1;
  1020.   }
  1021.   pt = (word32 far *)((word32)(pd_seg[last_po_pdi]) << 24);
  1022.   do {
  1023.     if ((pd[last_po_pdi] & (PT_P | PT_S)) == (PT_P | PT_S))
  1024.     {
  1025.       if ((pt[last_po_pti] & (PT_P | PT_S)) == (PT_P | PT_S))
  1026.       {
  1027.         rv = pt[last_po_pti] >> 12;
  1028.         v = ((word32)last_po_pdi << 22) | ((word32)last_po_pti << 12);
  1029.         if (!fInPageOutEverything)
  1030.           if ((v & 0xfffff000L) == ((tss_ptr->tss_eip + ARENA) & 0xfffff000L) ||
  1031.               (v & 0xfffff000L) == ((tss_ptr->tss_esp + ARENA) & 0xfffff000L))
  1032.           {
  1033. #if VERBOSE
  1034.             printf("\nskip: v=%08lx - ", v);
  1035. #endif
  1036.             goto bad_choice;
  1037.           }
  1038.         if (pt[last_po_pti] & (PT_C | PT_D))
  1039.         {
  1040.           pt[last_po_pti] |= PT_C;
  1041.           dblock = dalloc();
  1042.           memget(v, paging_buffer, 4096);
  1043. #if VERBOSE
  1044.           printf ("dout %08lx", ((word32)last_po_pdi<<22) | ((word32)last_po_pti<<12));
  1045. #endif
  1046.           dwrite(paging_buffer, dblock);
  1047.           pt[last_po_pti] &= 0xfff & ~PT_P; /* no longer present */
  1048.           pt[last_po_pti] |= (long)dblock << 12;
  1049.         }
  1050.         else
  1051.         {
  1052.           pt[last_po_pti] = PT_W | PT_S;
  1053. #if VERBOSE
  1054.           printf ("dflush %08lx", ((word32)last_po_pdi<<22) | ((word32)last_po_pti<<12));
  1055. #endif
  1056.         }
  1057.         if (topline_info)
  1058.           update_status(old_status, 79);
  1059.         return (word16)rv;
  1060.       }
  1061.     }
  1062.     else /* imagine we just checked the last entry */
  1063.       last_po_pti = 1023;
  1064.  
  1065. bad_choice:
  1066.     if (++last_po_pti == 1024)
  1067.     {
  1068.       last_po_pti = 0;
  1069.       if (++last_po_pdi == 1024)
  1070.         last_po_pdi = 0;
  1071.       pt = (word32 far *)((word32)(pd_seg[last_po_pdi]) << 24);
  1072.     }
  1073.   } while ((start_pdi != last_po_pdi) || (start_pti != last_po_pti));
  1074.   if (topline_info)
  1075.     update_status(old_status, 79);
  1076.   return 0xffff;
  1077. }
  1078.  
  1079. unsigned pd_dblock;
  1080.  
  1081. extern int valloc_initted;
  1082. extern void vfree_640(void);
  1083. extern void vrecover_640(void);
  1084.  
  1085. void page_out_everything(void)
  1086. {
  1087.   int pdi, i;
  1088.   word32 opde;
  1089.   unsigned ptb;
  1090.   void far *fp;
  1091.  
  1092.   if(use_DPMI)
  1093.   {
  1094.     saveDPMIstate();
  1095.     return;
  1096.   }
  1097.  
  1098.   fInPageOutEverything = 1;
  1099.  
  1100. #ifndef KEEP_ON_EXEC
  1101.   while (page_out(-1) != 0xffff)
  1102.   {
  1103.     vfree();
  1104.   }
  1105. #endif
  1106.   for (pdi=0; pdi<1024; pdi++)
  1107.     if (pd[pdi] & PT_P)
  1108.     {
  1109.       ptb = dalloc();
  1110.       opde = pd[pdi] & 0xfffff001L;
  1111.       fp = (word32 far *)((word32)pd_seg[pdi] << 24);
  1112.       movedata(FP_SEG(fp), FP_OFF(fp), _DS, FP_OFF(paging_buffer), 4096);
  1113.       dwrite(paging_buffer, ptb);
  1114.       vfree();
  1115.       pd[pdi] = (pd[pdi] & (0xFFF&~PT_P)) | ((word32)ptb<<12);
  1116.       for (i=pdi+1; i<1024; i++)
  1117.         if ((pd[i] & 0xfffff001L) == opde)
  1118.           pd[i] = pd[pdi];
  1119.     }
  1120.   movedata(FP_SEG(pd), FP_OFF(pd), _DS, FP_OFF(paging_buffer), 4096);
  1121.   pd_dblock = dalloc();
  1122.   dwrite(paging_buffer, pd_dblock);
  1123.   vfree();
  1124. #ifndef KEEP_ON_EXEC
  1125.   vcpi_flush();
  1126.   valloc_uninit();
  1127. #else
  1128.   vfree_640();
  1129. #endif
  1130. }
  1131.  
  1132. void page_in_everything(void)
  1133. {
  1134.   int pdi, i;
  1135.   word32 opde;
  1136.   unsigned ptb;
  1137.   word32 far *pt;
  1138.   unsigned pta;
  1139.  
  1140.   if(use_DPMI)
  1141.   {
  1142.     restoreDPMIstate();
  1143.     return;
  1144.   }
  1145.  
  1146.   fInPageOutEverything = 0;
  1147.  
  1148. #ifndef KEEP_ON_EXEC
  1149.   valloc_initted = 0;
  1150. #else
  1151.   vrecover_640();
  1152. #endif
  1153.   pta = valloc(VA_640);
  1154.   pd = (word32 far *)((word32)pta << 24);
  1155.   dread(paging_buffer, pd_dblock);
  1156.   dfree(pd_dblock);
  1157.   movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pd), FP_OFF(pd), 4096);
  1158.   for (pdi=0; pdi<1024; pdi++)
  1159.     if (pd[pdi] && !(pd[pdi] & PT_P))
  1160.     {
  1161.       pta = valloc(VA_640);
  1162.       opde = pd[pdi] & 0xfffff001L;
  1163.       pt = (word32 far *)((word32)pta << 24);
  1164.       ptb = (word16)(opde >> 12);
  1165.       dread(paging_buffer, ptb);
  1166.       dfree(ptb);
  1167.       movedata(_DS, FP_OFF(paging_buffer), FP_SEG(pt), FP_OFF(pt), 4096);
  1168.       if (pdi == 0)
  1169.         vcpi_pt = (word32 far *)((word32)pta << 24);
  1170.       pd[pdi] = pn2pte(pta, (pd[pdi] & 0xFFF) | PT_P);
  1171.       pd_seg[pdi] = pta;
  1172.       for (i=pdi+1; i<1024; i++)
  1173.         if ((pd[i] & 0xfffff001L) == opde)
  1174.         {
  1175.           pd[i] = pd[pdi];
  1176.           pd_seg[i] = pd_seg[pdi];
  1177.         }
  1178.     }
  1179. /* CB changes: two tables + page directory stuff */
  1180. /* OLD:
  1181.  * graphics_pt = (word32 far *)((long)pd_seg[0x380] << 24);
  1182.  * graphics_pt_lin = ptr2linear(graphics_pt);
  1183.  */
  1184.   graphics_pd    = &pd[0x380];
  1185.   graphics_pd_lin  = ptr2linear(graphics_pd);
  1186.   graphics_pt1           = (word32 far *)((word32)graphics_pd_seg[(word16)graphics_pt1_loc] << 24);
  1187.   graphics_pt2           = (word32 far *)((word32)graphics_pd_seg[(word16)graphics_pt2_loc] << 24);
  1188.   graphics_pt1_lin = ptr2linear(graphics_pt1);
  1189.   graphics_pt2_lin = ptr2linear(graphics_pt2);
  1190.   for(i = 0; i < 1024; i++) {
  1191.     graphics_pt1[i] = 0L;
  1192.     graphics_pt2[i] = 0L;
  1193.   }
  1194. /* end CB changes */
  1195. }
  1196.  
  1197.  
  1198. static word32 emu_start_ip_val = 0;
  1199.  
  1200. word32 emu_start_ip()
  1201. {
  1202.   return emu_start_ip_val;
  1203. }
  1204.  
  1205. int emu_install(char *filename)
  1206. {
  1207.   FILEHDR filehdr;
  1208.   AOUTHDR aouthdr;
  1209.   GNU_AOUT gnu_aout;
  1210.   int emu_f;
  1211.  
  1212.   areas[A_emu].first_addr = EMU_TEXT+ARENA;
  1213.   areas[A_emu].last_addr = EMU_TEXT-1+ARENA;
  1214.   areas[A_emu].foffset = 0;
  1215.  
  1216.   if (use_DPMI)
  1217.     return 0;
  1218.   if (filename == 0)
  1219.     return 0;
  1220.   emu_f = open(filename, O_RDONLY|O_BINARY);
  1221.   if (emu_f < 0)
  1222.   {
  1223.     fprintf(stderr, "Can't open 80387 emulator file <%s>\n", filename);
  1224.     return 0;
  1225.   }
  1226.   areas[A_emu].fileno = emu_f;
  1227.   
  1228.   read(emu_f, &filehdr, sizeof(filehdr));
  1229.   if (filehdr.f_magic != 0x14c)
  1230.   {
  1231.     lseek(emu_f, 0L, 0);
  1232.     read(emu_f, &gnu_aout, sizeof(gnu_aout));
  1233.     emu_start_ip_val = gnu_aout.entry;
  1234.     aouthdr.tsize = gnu_aout.tsize;
  1235.     aouthdr.dsize = gnu_aout.dsize;
  1236.     aouthdr.bsize = gnu_aout.bsize;
  1237.   }
  1238.   else
  1239.   {
  1240.     read(emu_f, &aouthdr, sizeof(aouthdr));
  1241.     emu_start_ip_val = aouthdr.entry;
  1242.   }
  1243.  
  1244.   areas[A_emu].last_addr += aouthdr.tsize + aouthdr.dsize + aouthdr.bsize + (emu_start_ip_val & 0xff);
  1245.   return 1;
  1246. }
  1247.  
  1248. word32 stack_used(void)
  1249. {
  1250.   int pdi,pti;
  1251.   word32 far *pt;
  1252.  
  1253.   for(pdi=0x140;pdi<0x240;pdi++)
  1254.     if( pd[pdi] & PT_I ) {  /* really should check for PT_P here, but */
  1255.       pt = (word32 far *)((word32)(pd_seg[pdi]) << 24);
  1256.       for(pti=0;pti<1024;pti++)
  1257.         if( pt[pti] & PT_I )
  1258.           return ((word32)(0x23f-pdi) << 22) | ((word32)(1024-pti) << 12);
  1259.     }
  1260.   return 0L;  /* No stack pd entries found! */
  1261. }
  1262.